崩溃日志收集与上报体系怎么搭建?
考察点
- 日志分级、落盘轮转
- minidump 崩溃上报与符号化
参考答案
1. 体系全景
三层日志:
1. JS 层日志(electron-log)→ 本地文件轮转 + 按需上报
2. 崩溃转储(crashReporter minidump)→ 自动上报 + 符号化
3. 渲染进程日志 → IPC 汇集到主进程统一落盘
2. JS 层日志
(1)electron-log 配置
const log = require('electron-log/main');
// 初始化(主进程)
log.initialize();
// 分级与格式
log.transports.file.level = 'info';
log.transports.file.format = '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] [{processType}] {text}';
// 轮转策略:按大小切分,保留最近 N 个
log.transports.file.maxSize = 10 * 1024 * 1024; // 单文件 10MB
log.transports.file.archiveLogFn = (oldLogFile) => {
// 归档压缩,最多保留 5 个历史文件
};
(2)渲染进程日志汇集
// 渲染进程的 console 自动转发到主进程(electron-log 能力)
log.initialize({ preload: true });
// 或手动:preload 桥接 log API,渲染侧调 api.log.info(...)
所有进程日志汇聚到同一文件(带 processType 区分),排查时不用东拼西凑。
(3)分级与采样
- 线上默认 info 级;debug/verbose 通过远程开关(配置下发)针对问题设备开启
- 高频日志采样(如心跳日志 1/100 采样),避免日志爆炸
3. 崩溃转储(minidump)
const { crashReporter } = require('electron');
crashReporter.start({
productName: 'MyAgent',
companyName: 'MyCompany',
submitURL: 'https://crash.example.com/api/minidump',
uploadToServer: true,
ignoreSystemCrashHandler: false,
// 附加业务字段,定位问题现场
extra: {
version: app.getVersion(),
channel: getUpdateChannel(),
},
});
- 采集的是进程级崩溃(段错误、原生层 crash),JS try/catch 抓不到的那类
- 产物是 minidump 文件(.dmp),需要 breakpad 符号表做符号化才能看到可读的堆栈
- 自建服务端可用 [mini-breakpad-server] 或直接把符号和 dmp 传 Sentry
4. 崩溃堆栈符号化
发布时:从构建产物提取符号文件(.sym/.pdb/dSYM)→ 归档到符号服务器
收到 dmp:符号化工具(minidump_stackwalk / Sentry)+ 符号文件 → 可读调用栈
要点:
- 每个发布版本的符号必须归档,丢符号 = 该版本崩溃无法分析
- JS 层错误还要 sourcemap 还原(构建时上传 sourcemap 到 Sentry,注意别公开分发)
5. 上报策略
- 崩溃即报:minidump 由 crashReporter 自动上传
- 日志按需拉取:全量日志太大,服务端下发"日志采集指令"→ agent 打包最近 N 天日志脱敏上传(用户隐私敏感字段要脱敏:路径中的用户名、token 等)
- 问题反馈入口:托盘菜单"问题反馈"一键打包日志+系统信息,用户授权后上传
6. 指标体系
按版本聚合:
- 崩溃率 = 崩溃设备数 / 活跃设备数(灰度发布的关键决策指标)
- 崩溃 TopN 堆栈聚类(同堆栈归并)
- JS 错误率、未捕获 rejection 数
新崩溃堆栈出现 → 告警 → 关联发布批次 → 决定停止放量或热修。
7. 常见坑
- crashReporter 要尽早 start(主进程入口),否则启动期崩溃采不到
- 每个进程类型都要启动(主进程 start 后渲染进程自动继承配置,但 utility process 要单独处理)
- 日志文件写入要异步队列化,崩溃瞬间同步写可能丢日志
- Windows 上 minidump 上传需要崩溃后下次启动才发(崩溃时进程已死)——启动时检查 pending 崩溃并上报
面试话术
体系三层:electron-log 分级轮转做 JS 日志(渲染进程汇集到主进程统一落盘);crashReporter 做 minidump 崩溃上报,关键是每版本符号归档 + 符号化;上报策略分崩溃即报与日志按需拉取(脱敏后)。最终形成按版本聚合的崩溃率指标,直接驱动灰度放量决策。
常见追问
- 用户没网时崩溃日志怎么办? 本地暂存,联网后补报;minidump 本身就保存在 crashes 目录。
- 怎么定位"没崩溃但功能异常"的问题? 远程日志开关 + 关键链路结构化埋点(traceId 串联一次操作的全链路日志)。